/****************************************************************
 *
 * Project: Handle ARM M4 STM32F407VG In 2 Weeks
 * 
 ****************************************************************/

/****************************************************************
 *
 *	Module		: "header file" mySpi.c
 *  Tool		: KeilC ARM 4.22a
 *	Chip		: STM32F407VG
 * 	History		: 9/12/2011
 *	Description	: Day 7
				  + My library to exchange data via Spi peripheral
				  + Reference to header file "mySpi.h"
 *				
 *	Author		: Dang Anh Tung			
 *	Description	: www.payitforward.edu.vn
 *				
 *
 ****************************************************************/

 
 /****************************************************************
 * 							IMPORT
 ****************************************************************/
  #include "stm32f4xx.h"
  #include "mySpi.h"
  #include "stm32f4xx_spi.h"
  #include "stm32f4xx_gpio.h"

 /****************************************************************
 * 							GLOBAL
 ****************************************************************/

DMA_InitTypeDef DmaSpi1TxStruct;
char DmaSpi1TxBuffer[20];

DMA_InitTypeDef DmaSpi1RxStruct;
char DmaSpi1RxBuffer[20];

DMA_InitTypeDef DmaSpi2TxStruct;
char DmaSpi2TxBuffer[20];

DMA_InitTypeDef DmaSpi2RxStruct;
char DmaSpi2RxBuffer[20];

DMA_InitTypeDef DmaSpi3TxStruct;
char DmaSpi3TxBuffer[20];

DMA_InitTypeDef DmaSpi3RxStruct;
char DmaSpi3RxBuffer[20];


/*****************************************************************
* 							DEFINE
******************************************************************/


 /****************************************************************
 * 						   FUNCTIONS
 ****************************************************************/

/****************************************************************
** Function name:	    myLis302PowerUp
**
** Descriptions:		Turn on LIS302 sensor
**
** parameters:		    None
** Returned value:		None
** 
*****************************************************************/

void myLis302PowerUp(void)
{
	uint8_t writeBuffer[5];
	uint8_t readBuffer[5];

	writeBuffer[0] =  CTRL_REG1_FIRST_TIME;
	mySpiWriteBytes(SPI1, writeBuffer, CTRL_REG1_ADDR , 1);
	//use to debug purpose; the return value readBuffer[0] must be 0x3B
 	mySpiReadBytes(SPI1, readBuffer, WHO_AM_I_ADDR, 1);
	readBuffer[0] = readBuffer[0];	
}


/****************************************************************
** Function name:	    mySpiInit
**
** Descriptions:		Init all SPI that wil be used in IMU
**
** parameters:		    None
** Returned value:		None
** 
*****************************************************************/

void mySpiInit(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitTypeDef SPI_GPIO_InitStructure;
    SPI_InitTypeDef  SPI_InitStructure;

	/*
	*	Init SPI1 MISO, MOSI
	*	SPI1_TX at PA7 ( MOSI)
	*	SPI1_RX at PA6 ( MISO)
	*	SPI1_CLK at PA5
	*	SPI1_CS at PE3
	*/

	//	Enable clock SPI1 peripheral
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
	//	Enable clock to PORTA, PORTE
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
	//	Configure PE3 Chip select
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOE, &GPIO_InitStructure);
	//	Deselect : Chip Select high to idle the line
	GPIO_SetBits(GPIOE, GPIO_Pin_3);
    //	Configure alternate function to pins 
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);   //TX
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);   //RX
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);	  //CLK
	//  Init GPIO
	SPI_GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
	SPI_GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	SPI_GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	SPI_GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;		 //note 
	//	MOSI-TX, MISO-RX, CLK
	SPI_GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;  
	GPIO_Init(GPIOA, &SPI_GPIO_InitStructure);
    //  SPI configuration 
	SPI_I2S_DeInit(SPI1);  
	SPI_InitStructure.SPI_Direction 		= SPI_Direction_2Lines_FullDuplex;		//	2-way
	SPI_InitStructure.SPI_DataSize 			= SPI_DataSize_8b;						//	8 bits
	SPI_InitStructure.SPI_CPOL 				= SPI_CPOL_Low;							//
	SPI_InitStructure.SPI_CPHA 				= SPI_CPHA_1Edge;
	SPI_InitStructure.SPI_NSS 				= SPI_NSS_Soft;							//	pin Chip-select be controlled by software
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
	SPI_InitStructure.SPI_FirstBit 			= SPI_FirstBit_MSB;						//	MSB bit first out
	SPI_InitStructure.SPI_CRCPolynomial 	= 7;									//	0007 is reset value
	SPI_InitStructure.SPI_Mode 				= SPI_Mode_Master;						//	master mode
	SPI_Init(SPI1, &SPI_InitStructure);
	//	Enable SPI1
    SPI_Cmd(SPI1, ENABLE);
	//	Enable DMA request	
	//	SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx|SPI_I2S_DMAReq_Rx, ENABLE);
 
	
//	/*
//	*	Init SPI2 MISO, MOSI
//	*	SPI1_TX at PB15 ( MOSI)
//	*	SPI1_RX at PB14 ( MISO)
//	*	SPI1_CLK at PB13
//	*	SPI1_STE at PB12 : chip select
//	*	SPI1_RST at PA8	 : reset
//	*/
//	//	Enable clock SPI2 peripheral
//	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
//	//	Enable clock to PORTB, PORTA
// 	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
// 	//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//	//	Configure PB12 Chip select, PA8 reset
//	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
//	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
//	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_12;
//	GPIO_Init(GPIOB, &GPIO_InitStructure);
//	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8;
//	GPIO_Init(GPIOA, &GPIO_InitStructure);
//	//	Deselect these pins
//	GPIO_SetBits(GPIOB, GPIO_Pin_12);
//	GPIO_SetBits(GPIOA, GPIO_Pin_8);
//    //	Configure alternate function to TX RX CLK pins 
//	GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);   	//TX
//	GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2);   	//RX
//	GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2);	//CLK
//
//	//  Init SPI_GPIO
//	SPI_GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
//	SPI_GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//	SPI_GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//	SPI_GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;		 //note 
//	//	MOSI-TX, MISO-RX, CLK
//	SPI_GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; 
//	GPIO_Init(GPIOB, &SPI_GPIO_InitStructure);
//
//    //  SPI configuration 
//	SPI_I2S_DeInit(SPI2);  
//	SPI_InitStructure.SPI_Direction 		= SPI_Direction_2Lines_FullDuplex;		//	2-way
//	SPI_InitStructure.SPI_DataSize 			= SPI_DataSize_8b;						//	8 bits
//	SPI_InitStructure.SPI_CPOL 				= SPI_CPOL_Low;							//
//	SPI_InitStructure.SPI_CPHA 				= SPI_CPHA_1Edge;
//	SPI_InitStructure.SPI_NSS 				= SPI_NSS_Soft;							//	pin Chip-select be controlled by software
//	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
//	SPI_InitStructure.SPI_FirstBit 			= SPI_FirstBit_MSB;						//	MSB bit first out
//	SPI_InitStructure.SPI_CRCPolynomial 	= 7;									//	0007 is reset value
//	SPI_InitStructure.SPI_Mode 				= SPI_Mode_Master;						//	master mode
//	SPI_Init(SPI2, &SPI_InitStructure);
//	//	Enable SPI2
//    SPI_Cmd(SPI2, ENABLE);
//	//	Enable DMA request	
//	//	SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx|SPI_I2S_DMAReq_Rx, ENABLE);

	
	/*
	*	Init SPI3 MISO, MOSI
	*	SPI3_TX = SD_MOSI at PB5
	*	SPI3_RX = SD_MISO at PB4
	*	SPI3_CLK = SD_CLK at PB3 (NOTE PB3 = SWO but this pin is not used in SWIO--> can use this pin for GPIO purpose)
	*	SPI3_STE = SD_CS at PA15
	*/
	//	Enable clock SPI3 peripheral
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
	//	Enable clock to PORTB, PORTA
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	//	Configure PA15 Chip select
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL; 		//sua here
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_15;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	//	Deselect CS pin
	GPIO_SetBits(GPIOA, GPIO_Pin_15);
    //	Configure alternate function to TX RX CLK pins 
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI3);   	//TX
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI3);   	//RX
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI3);		//CLK

	//  Init SPI_GPIO
	SPI_GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
	SPI_GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	SPI_GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	SPI_GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL ;		 //note 
	//	MOSI-TX, MISO-RX, CLK
	SPI_GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_3; 
	GPIO_Init(GPIOB, &SPI_GPIO_InitStructure);

    //  SPI configuration 
	SPI_I2S_DeInit(SPI3);  
	SPI_InitStructure.SPI_Direction 		= SPI_Direction_2Lines_FullDuplex;		//	2-way
	SPI_InitStructure.SPI_DataSize 			= SPI_DataSize_8b;						//	8 bits
	SPI_InitStructure.SPI_CPOL 				= SPI_CPOL_Low;							//
	SPI_InitStructure.SPI_CPHA 				= SPI_CPHA_1Edge;
	SPI_InitStructure.SPI_NSS 				= SPI_NSS_Soft;							//	pin Chip-select be controlled by software
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
	SPI_InitStructure.SPI_FirstBit 			= SPI_FirstBit_MSB;						//	MSB bit first out
	SPI_InitStructure.SPI_CRCPolynomial 	= 7;									//	0007 is reset value
	SPI_InitStructure.SPI_Mode 				= SPI_Mode_Master;						//	master mode
	SPI_Init(SPI3, &SPI_InitStructure);
	//	Enable SPI3
    SPI_Cmd(SPI3, ENABLE);
	//	Enable DMA request	
//	SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx|SPI_I2S_DMAReq_Rx, ENABLE);


}


/****************************************************************
** Function name:	    myDmaSpiInit
**
** Descriptions:		Init all DMA SPI that will be used
**
** parameters:		    None
** Returned value:		None
** 
*****************************************************************/

void myDmaSpiInit(void)
{

	/*
	*	DMA2 SPI1: TX Stream 3, channel 3
	*	DMA = { DMA_SPI1_TX_STREAM, DMA_SPI1_TX_CHANNEL, Memory To Peripheral...}
	*
	*/
	
	//	Enable clock to DMA2
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
	//default reset state
	DMA_DeInit(DMA_SPI1_TX_STREAM);	

			
	DmaSpi1TxStruct.DMA_Channel 				= DMA_SPI1_TX_CHANNEL;
	DmaSpi1TxStruct.DMA_DIR 					= DMA_DIR_MemoryToPeripheral;
	DmaSpi1TxStruct.DMA_Memory0BaseAddr 		= (uint32_t)DmaSpi1TxBuffer; 
    DmaSpi1TxStruct.DMA_PeripheralBaseAddr 		= DMA_SPI1_TX_PERIPH;  		 
	DmaSpi1TxStruct.DMA_PeripheralDataSize 		= DMA_PeripheralDataSize_Byte;
	DmaSpi1TxStruct.DMA_MemoryDataSize 			= DMA_MemoryDataSize_Byte;
	DmaSpi1TxStruct.DMA_Priority 				= DMA_SPI1_TX_PRIORITY;
	DmaSpi1TxStruct.DMA_FIFOMode 				= DMA_FIFOMode_Disable;				//direct mode
	DmaSpi1TxStruct.DMA_FIFOThreshold 			= DMA_FIFOThreshold_Full;
	DmaSpi1TxStruct.DMA_MemoryInc 				= DMA_MemoryInc_Enable;
	DmaSpi1TxStruct.DMA_PeripheralInc 			= DMA_PeripheralInc_Disable;
	DmaSpi1TxStruct.DMA_Mode 					= DMA_Mode_Normal;
	DmaSpi1TxStruct.DMA_BufferSize 				= (uint32_t)7 ;						//JUST init value
	DmaSpi1TxStruct.DMA_MemoryBurst 			= DMA_MemoryBurst_Single;
	DmaSpi1TxStruct.DMA_PeripheralBurst 		= DMA_PeripheralBurst_Single;
	//	disable DMA Stream Transfer Complete interrupt
	DMA_ITConfig(DMA_SPI1_TX_STREAM, DMA_IT_TC, ENABLE);
	DMA_Init(DMA_SPI1_TX_STREAM, &DmaSpi1TxStruct);	


	/*
	*	DMA2 SPI1: RX Stream 2, channel 3
	*	DMA = { DMA_SPI1_RX_STREAM, DMA_SPI1_RX_CHANNEL, ...}
	*
	*/
	
	//	Enable clock to DMA2
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
	//default reset state
	DMA_DeInit(DMA_SPI1_RX_STREAM);				
	DmaSpi1RxStruct.DMA_Channel 				= DMA_SPI1_RX_CHANNEL;
	DmaSpi1RxStruct.DMA_DIR 					= DMA_DIR_PeripheralToMemory;
	DmaSpi1RxStruct.DMA_Memory0BaseAddr 		= (uint32_t)DmaSpi1RxBuffer; 
    DmaSpi1RxStruct.DMA_PeripheralBaseAddr 		= DMA_SPI1_RX_PERIPH;  		 
	DmaSpi1RxStruct.DMA_PeripheralDataSize 		= DMA_PeripheralDataSize_Byte;
	DmaSpi1RxStruct.DMA_MemoryDataSize 			= DMA_MemoryDataSize_Byte;
	DmaSpi1RxStruct.DMA_Priority 				= DMA_SPI1_RX_PRIORITY;
	DmaSpi1RxStruct.DMA_FIFOMode 				= DMA_FIFOMode_Disable;				//direct mode
	DmaSpi1RxStruct.DMA_FIFOThreshold 			= DMA_FIFOThreshold_Full;
	DmaSpi1RxStruct.DMA_MemoryInc 				= DMA_MemoryInc_Enable;
	DmaSpi1RxStruct.DMA_PeripheralInc 			= DMA_PeripheralInc_Disable;
	DmaSpi1RxStruct.DMA_Mode 					= DMA_Mode_Normal;
	DmaSpi1RxStruct.DMA_BufferSize 				= (uint32_t)7 ;						//JUST init value
	DmaSpi1RxStruct.DMA_MemoryBurst 			= DMA_MemoryBurst_Single;
	DmaSpi1RxStruct.DMA_PeripheralBurst 		= DMA_PeripheralBurst_Single;
	//Enable DMA Stream Transfer Complete interrupt
	DMA_ITConfig(DMA_SPI1_RX_STREAM, DMA_IT_TC, ENABLE);
	DMA_Init(DMA_SPI1_RX_STREAM, &DmaSpi1RxStruct);	

	/*
	*	DMA1 SPI2: TX Stream 4, channel 0
	*	DMA = { DMA_SPI2_TX_STREAM, DMA_SPI2_TX_CHANNEL, Memory To Peripheral...}
	*
	*/
	
	//	Enable clock to DMA1
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
	//default reset state
	DMA_DeInit(DMA_SPI2_TX_STREAM);				
	DmaSpi2TxStruct.DMA_Channel 				= DMA_SPI2_TX_CHANNEL;
	DmaSpi2TxStruct.DMA_DIR 					= DMA_DIR_MemoryToPeripheral;
	DmaSpi2TxStruct.DMA_Memory0BaseAddr 		= (uint32_t)DmaSpi2TxBuffer; 
    DmaSpi2TxStruct.DMA_PeripheralBaseAddr 		= DMA_SPI2_TX_PERIPH;  		 
	DmaSpi2TxStruct.DMA_PeripheralDataSize 		= DMA_PeripheralDataSize_Byte;
	DmaSpi2TxStruct.DMA_MemoryDataSize 			= DMA_MemoryDataSize_Byte;
	DmaSpi2TxStruct.DMA_Priority 				= DMA_SPI2_TX_PRIORITY;
	DmaSpi2TxStruct.DMA_FIFOMode 				= DMA_FIFOMode_Enable;				//direct mode
	DmaSpi2TxStruct.DMA_FIFOThreshold 			= DMA_FIFOThreshold_Full;
	DmaSpi2TxStruct.DMA_MemoryInc 				= DMA_MemoryInc_Enable;
	DmaSpi2TxStruct.DMA_PeripheralInc 			= DMA_PeripheralInc_Disable;
	DmaSpi2TxStruct.DMA_Mode 					= DMA_Mode_Normal;
	DmaSpi2TxStruct.DMA_BufferSize 				= (uint32_t)7 ;						//JUST init value
	DmaSpi2TxStruct.DMA_MemoryBurst 			= DMA_MemoryBurst_Single;
	DmaSpi2TxStruct.DMA_PeripheralBurst 		= DMA_PeripheralBurst_Single;
	//Enable DMA Stream Transfer Complete interrupt
	DMA_ITConfig(DMA_SPI2_TX_STREAM, DMA_IT_TC, ENABLE);
	DMA_Init(DMA_SPI2_TX_STREAM, &DmaSpi2TxStruct);	

	/*
	*	DMA1 SPI2: RX Stream 3, channel 0
	*	DMA = { DMA_SPI2_RX_STREAM, DMA_SPI2_RX_CHANNEL, ...}
	*
	*/
	
	//	Enable clock to DMA1
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
	//default reset state
	DMA_DeInit(DMA_SPI2_RX_STREAM);				
	DmaSpi2RxStruct.DMA_Channel 				= DMA_SPI2_RX_CHANNEL;
	DmaSpi2RxStruct.DMA_DIR 					= DMA_DIR_PeripheralToMemory;
	DmaSpi2RxStruct.DMA_Memory0BaseAddr 		= (uint32_t)DmaSpi2RxBuffer; 
    DmaSpi2RxStruct.DMA_PeripheralBaseAddr 		= DMA_SPI2_RX_PERIPH;  		 
	DmaSpi2RxStruct.DMA_PeripheralDataSize 		= DMA_PeripheralDataSize_Byte;
	DmaSpi2RxStruct.DMA_MemoryDataSize 			= DMA_MemoryDataSize_Byte;
	DmaSpi2RxStruct.DMA_Priority 				= DMA_SPI2_RX_PRIORITY;
	DmaSpi2RxStruct.DMA_FIFOMode 				= DMA_FIFOMode_Enable;				//direct mode
	DmaSpi2RxStruct.DMA_FIFOThreshold 			= DMA_FIFOThreshold_Full;
	DmaSpi2RxStruct.DMA_MemoryInc 				= DMA_MemoryInc_Enable;
	DmaSpi2RxStruct.DMA_PeripheralInc 			= DMA_PeripheralInc_Disable;
	DmaSpi2RxStruct.DMA_Mode 					= DMA_Mode_Normal;
	DmaSpi2RxStruct.DMA_BufferSize 				= (uint32_t)7 ;						//JUST init value
	DmaSpi2RxStruct.DMA_MemoryBurst 			= DMA_MemoryBurst_Single;
	DmaSpi2RxStruct.DMA_PeripheralBurst 		= DMA_PeripheralBurst_Single;
	//Enable DMA Stream Transfer Complete interrupt
	DMA_ITConfig(DMA_SPI2_RX_STREAM, DMA_IT_TC, ENABLE);
	DMA_Init(DMA_SPI2_RX_STREAM, &DmaSpi2RxStruct);
	
	/*
	*	DMA1 SPI3: TX Stream 5, channel 0
	*	DMA = { DMA_SPI3_TX_STREAM, DMA_SPI3_TX_CHANNEL, Memory To Peripheral...}
	*
	*/
	
	//	Enable clock to DMA1
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
	//default reset state
	DMA_DeInit(DMA_SPI3_TX_STREAM);				
	DmaSpi3TxStruct.DMA_Channel 				= DMA_SPI3_TX_CHANNEL;
	DmaSpi3TxStruct.DMA_DIR 					= DMA_DIR_MemoryToPeripheral;
	DmaSpi3TxStruct.DMA_Memory0BaseAddr 		= (uint32_t)DmaSpi3TxBuffer; 
    DmaSpi3TxStruct.DMA_PeripheralBaseAddr 		= DMA_SPI3_TX_PERIPH;  		 
	DmaSpi3TxStruct.DMA_PeripheralDataSize 		= DMA_PeripheralDataSize_Byte;
	DmaSpi3TxStruct.DMA_MemoryDataSize 			= DMA_MemoryDataSize_Byte;
	DmaSpi3TxStruct.DMA_Priority 				= DMA_SPI3_TX_PRIORITY;
	DmaSpi3TxStruct.DMA_FIFOMode 				= DMA_FIFOMode_Enable;				//direct mode
	DmaSpi3TxStruct.DMA_FIFOThreshold 			= DMA_FIFOThreshold_Full;
	DmaSpi3TxStruct.DMA_MemoryInc 				= DMA_MemoryInc_Enable;
	DmaSpi3TxStruct.DMA_PeripheralInc 			= DMA_PeripheralInc_Disable;
	DmaSpi3TxStruct.DMA_Mode 					= DMA_Mode_Normal;
	DmaSpi3TxStruct.DMA_BufferSize 				= (uint32_t)7 ;						//JUST init value
	DmaSpi3TxStruct.DMA_MemoryBurst 			= DMA_MemoryBurst_Single;
	DmaSpi3TxStruct.DMA_PeripheralBurst 		= DMA_PeripheralBurst_Single;
	//Enable DMA Stream Transfer Complete interrupt
	DMA_ITConfig(DMA_SPI3_TX_STREAM, DMA_IT_TC, ENABLE);
	DMA_Init(DMA_SPI3_TX_STREAM, &DmaSpi3TxStruct);
	
	/*
	*	DMA1 SPI3: RX Stream 2, channel 0
	*	DMA = { DMA_SPI3_RX_STREAM, DMA_SPI3_RX_CHANNEL, ...}
	*
	*/
	
	//	Enable clock to DMA1
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
	//default reset state
	DMA_DeInit(DMA_SPI3_RX_STREAM);				
	DmaSpi3RxStruct.DMA_Channel 				= DMA_SPI3_RX_CHANNEL;
	DmaSpi3RxStruct.DMA_DIR 					= DMA_DIR_PeripheralToMemory;
	DmaSpi3RxStruct.DMA_Memory0BaseAddr 		= (uint32_t)DmaSpi3RxBuffer; 
    DmaSpi3RxStruct.DMA_PeripheralBaseAddr 		= DMA_SPI3_RX_PERIPH;  		 
	DmaSpi3RxStruct.DMA_PeripheralDataSize 		= DMA_PeripheralDataSize_Byte;
	DmaSpi3RxStruct.DMA_MemoryDataSize 			= DMA_MemoryDataSize_Byte;
	DmaSpi3RxStruct.DMA_Priority 				= DMA_SPI3_RX_PRIORITY;
	DmaSpi3RxStruct.DMA_FIFOMode 				= DMA_FIFOMode_Enable;				//direct mode
	DmaSpi3RxStruct.DMA_FIFOThreshold 			= DMA_FIFOThreshold_Full;
	DmaSpi3RxStruct.DMA_MemoryInc 				= DMA_MemoryInc_Enable;
	DmaSpi3RxStruct.DMA_PeripheralInc 			= DMA_PeripheralInc_Disable;
	DmaSpi3RxStruct.DMA_Mode 					= DMA_Mode_Normal;
	DmaSpi3RxStruct.DMA_BufferSize 				= (uint32_t)7 ;						//JUST init value
	DmaSpi3RxStruct.DMA_MemoryBurst 			= DMA_MemoryBurst_Single;
	DmaSpi3RxStruct.DMA_PeripheralBurst 		= DMA_PeripheralBurst_Single;
	//Enable DMA Stream Transfer Complete interrupt
	DMA_ITConfig(DMA_SPI3_RX_STREAM, DMA_IT_TC, ENABLE);
	DMA_Init(DMA_SPI3_RX_STREAM, &DmaSpi3RxStruct);	
			
}


/****************************************************************
** Function name:	    myDmaSpiInterruptInit
**
** Descriptions:		Init all DMA Interrupt that will be used
**
** parameters:		    None
** Returned value:		None
** 
*****************************************************************/
	
void myDmaSpiInterruptInit(void)
{
	NVIC_InitTypeDef NVIC_InitStruct;

	
	/*
	*	DMA2 SPI1 TX Interrupt
	*
	*/	

	NVIC_InitStruct.NVIC_IRQChannel = DMA_SPI1_TX_STREAM_IRQ;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;			  //sub- receive interrupt highest = 0
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);							// disable TC flag of trasmission 

 	/*
	*	DMA2 SPI1 RX Interrupt
	*
	*/
		
	NVIC_InitStruct.NVIC_IRQChannel = DMA_SPI1_RX_STREAM_IRQ;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;			  //sub- receive interrupt highest = 0
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);
  	

	/*
	*	DMA1 SPI2 TX Interrupt
	*
	*/	

	NVIC_InitStruct.NVIC_IRQChannel = DMA_SPI2_TX_STREAM_IRQ;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;			  //sub- receive interrupt highest = 0
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);

 	/*
	*	DMA1 SPI2 RX Interrupt
	*
	*/
		
	NVIC_InitStruct.NVIC_IRQChannel = DMA_SPI2_RX_STREAM_IRQ;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;			  //sub- receive interrupt highest = 0
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);

	/*
	*	DMA1 SPI3 TX Interrupt
	*
	*/	

	NVIC_InitStruct.NVIC_IRQChannel = DMA_SPI3_TX_STREAM_IRQ;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;			  //sub- receive interrupt highest = 0
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);

 	/*
	*	DMA1 SPI3 RX Interrupt
	*
	*/
		
	NVIC_InitStruct.NVIC_IRQChannel = DMA_SPI3_RX_STREAM_IRQ;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;			  //sub- receive interrupt highest = 0
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);

}

/****************************************************************
** Function name:	    mySpiExchangeByte
**
** Descriptions:		Exchange 1 byte with slave : transmitt 1 byte & receive 1 byte
**
** parameters:		    SPIx x = 1,2,3 
** Returned value:		None
** 
*****************************************************************/
    
uint8_t mySpiExchangeByte(SPI_TypeDef* SPIx, uint8_t byte)
{
	// Loop while DR register in not emplty 
	while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
	
	// Send byte through the SPIx peripheral
	SPI_I2S_SendData(SPIx, byte);
	
	//	Wait to receive a byte
	while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
	
	// Return the byte read from the SPI bus 
	return SPI_I2S_ReceiveData(SPIx);
}

/****************************************************************
** Function name:	    mySpiReadBytes
**
** Descriptions:		Read multi-bytes (numByte) continuously begin at start address in SPI slave by the NORMAL BUS
**
** parameters:		    SPIx x = 1,2,3 
** Returned value:		None
** 
*****************************************************************/
	
void mySpiReadBytes(SPI_TypeDef* SPIx, uint8_t *readBuffer, uint8_t startAddr, uint32_t numByte)
{
	if(numByte > 1)
	{
		//read multi-byte in sequential register begin with given address
		startAddr |= READ_INCREMENT_ADDR;
	}
	else
	{
		//read multi-byte in only 1 register with given address
		startAddr |= READ_UNCHANGE_ADDR;
	}

	/*
	*	Set chip select Low at the start of the transmission
	*/
	if ( SPIx == SPI1)		GPIO_ResetBits(GPIOE, GPIO_Pin_3); 
	else if (SPIx == SPI2)	GPIO_ResetBits(GPIOB, GPIO_Pin_12); 
	else if (SPIx == SPI3)	{ ; }//do some thing with SPI3 here
	else return;

	// Send the Address of the indexed register
	mySpiExchangeByte(SPIx, startAddr);
	// Receive the data that will be read from the device (MSB First)
	while(numByte > 0x00)
	{
		// Send dummy byte (0x00) to generate the SPI clock to LIS302DL (Slave device)
		*readBuffer = mySpiExchangeByte(SPIx, DUMMY_BYTE);
		numByte--;
		readBuffer++;
	}

	/*
	* Set chip select High at the end of the transmission 
	*/
	if ( SPIx == SPI1)		GPIO_SetBits(GPIOE, GPIO_Pin_3); 
	else if (SPIx == SPI2)	GPIO_SetBits(GPIOB, GPIO_Pin_12); 
	else if (SPIx == SPI3)	{ ; }//do some thing with SPI3 here
	else return;				 // should not reach here	  	 
}


/****************************************************************
** Function name:	    mySpiWriteBytes
**
** Descriptions:		Write multi-byte (numByte) continuously begin at start address in SPI slave	by the NORMAL BUS
**
** parameters:		    SPIx x = 1,2,3 
** Returned value:		None
** 
*****************************************************************/

void mySpiWriteBytes(SPI_TypeDef* SPIx, uint8_t *writeBuffer, uint8_t startAddr, uint32_t numByte)
{

	if(numByte > 1)
	{
		//write multi-byte in sequential register begin with given address
		startAddr |= WRITE_INCREMENT_ADDR;
	}
	else
	{
		//write multi-byte in only 1 register with given address
		startAddr |= WRITE_UNCHANGE_ADDR;
	}

  	/*
	*	Set chip select Low at the start of the transmission
	*/
	if ( SPIx == SPI1)		GPIO_ResetBits(GPIOE, GPIO_Pin_3); 
	else if (SPIx == SPI2)	GPIO_ResetBits(GPIOB, GPIO_Pin_12); 
	else if (SPIx == SPI3)	{ ; }//do some thing with SPI3 here
	else return;

	// Send the Address of the indexed register
	mySpiExchangeByte(SPIx, startAddr);
  	// Send the data that will be written into the device (MSB First) 
	while(numByte >= 0x01)
	{
		mySpiExchangeByte(SPIx, *writeBuffer);
	 	numByte--;
		writeBuffer++;
	}
  
	/*
	* Set chip select High at the end of the transmission 
	*/
	if ( SPIx == SPI1)		GPIO_SetBits(GPIOE, GPIO_Pin_3); 
	else if (SPIx == SPI2)	GPIO_SetBits(GPIOB, GPIO_Pin_12); 
	else if (SPIx == SPI3)	{ ; }//do some thing with SPI3 here
	else return;				 // should not reach here	
}

/****************************************************************
** Function name:	    mySpiReadDma
**
** Descriptions:		Read multi-bytes (numByte) continuously begin at start address in SPI slave by the DMA BUS
**
** parameters:		    SPIx x = 1,2,3 
**						DMAy_StreamRead  = dma_stream_tx
**						DMAy_StreamWrite = dma_stream_rx
** Returned value:		None
** 
*****************************************************************/

void mySpiReadDma(DMA_Stream_TypeDef* DMA_StreamRx,DMA_Stream_TypeDef* DMA_StreamTx, SPI_TypeDef* SPIx, uint8_t *readBuffer, uint8_t startAddr, uint32_t numByte)
{
	uint32_t i;
	while ((DMA_GetCmdStatus(DMA_StreamRx) == ENABLE) || ( DMA_GetCmdStatus(DMA_StreamTx) == ENABLE));

	//	Using 2 buffer to exchange data with slave, Init buffer
	DmaSpi1TxBuffer[0] =  startAddr | READ_INCREMENT_ADDR;
	for ( i = 1; i <= numByte; i++)
	{
		DmaSpi1TxBuffer[i] = DUMMY_BYTE;
	}
	//set buffer size: numByte + 1
	DmaSpi1TxStruct.DMA_Memory0BaseAddr = (uint32_t)DmaSpi1TxBuffer;
	DmaSpi1RxStruct.DMA_Memory0BaseAddr = (uint32_t)readBuffer;
	DmaSpi1TxStruct.DMA_BufferSize 		= numByte + 1;
	DmaSpi1RxStruct.DMA_BufferSize 		= numByte + 1;
	//set buffer pointer: 
	DMA_Init(DMA_StreamTx, &DmaSpi1TxStruct);
	DMA_Init(DMA_StreamRx,  &DmaSpi1RxStruct);	
	
	/*
	*	Set chip select Low at the start of the transmission
	*   This bit will be set in interrupt after receive end
	*/
	if ( SPIx == SPI1)		GPIO_ResetBits(GPIOE, GPIO_Pin_3); 
	else if (SPIx == SPI2)	GPIO_ResetBits(GPIOB, GPIO_Pin_12); 
	else if (SPIx == SPI3)	{ ; }//do some thing with SPI3 here
	else return;
	//ENABLE DMA SPI TX-RX
	DMA_Cmd(DMA_StreamTx, ENABLE); 		//TX
	DMA_Cmd(DMA_StreamRx, ENABLE); 	    //RX
	while((DMA_GetCmdStatus(DMA_StreamRx) == DISABLE)||(DMA_GetCmdStatus(DMA_StreamTx) == DISABLE))
	{
		GPIO_SetBits(GPIOD, GPIO_Pin_12);
	}

}



 /****************************************************************
 * 						   FUNCTIONS FOR SD CARD : SPI2, PB12: CS pin
 ****************************************************************/
 void SPI_CS_Low(void)
 {
 	GPIO_ResetBits(GPIOA, GPIO_Pin_15);
 }
 void SPI_CS_High(void)
 {
 	GPIO_SetBits(GPIOA, GPIO_Pin_15);
 }
 void SD_SPI_Init(void)
 {
 	mySpiInit();
 }
 uint8_t SPI_RecvByte(void)
 {
 	return mySpiExchangeByte(SPI3, 0xFF);
 }
 uint8_t SPI_SendByte (uint8_t data)
 {
 	return mySpiExchangeByte(SPI3, data);
 }




/****************************************************************
 * END OF standard form.c
 ****************************************************************/

